package thread.learn;


import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import static thread.learn.MyData.addRandom2Map;

class MyData {

    volatile int number = 0;

    public static final Map<String, Object> map = new HashMap<>();

    AtomicInteger i = new AtomicInteger(0);

    public void add2Ten(){
        this.number = 10;
    }

    public /*synchronized*/ void addPlusPlus(){
        number++;
    }
    public void addPlusPlus2(){
        i.getAndIncrement();
    }

    public static void addRandom2Map(){
        map.put(UUID.randomUUID().toString(), "");
    }
}
/**
 * 1. 可见性
 * 2. 不保证原子性
 *      (原子性是什么意思:
 *          不可分割,完整性,某个线程正在做某件事时,不可内打断
 *      )
 *
 * 3. 有序性(禁止指令重排)
 *
 * @author jiangwz
 * @create 2019/9/13.
 */
public class VolatileDemo {

    /**
     * 由于没有加volatile所以没有可以性,主线程结束不了
     * @param args
     */
    public static void main(String[] args){

        testMapVisibility();
//        testVisibility();
//        testAtomicity();



        String a = "11";
    }

    /**
     * 测试其没有原子性(每次结果都少于10000)
     */
    private static void testAtomicity() {
        CountDownLatch latch = new CountDownLatch(10);
        MyData myData = new MyData();
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                for (int j = 0; j < 1000; j++) {
                    myData.addPlusPlus();
//                    myData.addPlusPlus2();
                }
                latch.countDown();
            }, String.valueOf(i)).start();
        }

        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(myData.number);
//        System.out.println(myData.i);
    }

    /**
     * 测试可见性
     */
    private static void testVisibility() {
        MyData myData = new MyData();
        new Thread(() -> {
            String name = Thread.currentThread().getName();
            System.out.println(name + "线程准备休眠3秒");
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
            }
            System.out.println(name + "线程结束休眠");
            myData.add2Ten();
        }," A").start();
        while (myData.number == 0) {

        }
        System.out.println(Thread.currentThread().getName() + " 结束.");
    }

    private static void testMapVisibility(){
        new Thread(() -> {
            String name = Thread.currentThread().getName();
            System.out.println(name + "线程准备休眠3秒");
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
            }
            System.out.println(name + "线程结束休眠");
            addRandom2Map();
        }," A").start();
        while (MyData.map.size() == 0) {
            // 加了打印 就会同步 可以看底层源码
            System.out.println(11);

        }
        System.out.println(Thread.currentThread().getName() + " 结束.");
    }

}

